package alexAI;

import java.util.ArrayList;





public class AlphaBeta {
	
	private static AlphaBeta instance;
	private boolean white = true,
					black = false;
	//private Board board;
	private boolean cutOff = false ;
	private Game game;
	private int pos;
	
	private AlphaBeta() {
		game = new Game();
	}
	public static AlphaBeta getInstance() {
		if(instance == null)
				instance = new AlphaBeta();
		return instance;
	}


	//*************
	// First call, alpha = -infinity and beta = +infinity
	//*************
    public int minimaxAB( boolean min, int depth, int alpha, int beta) {
    	//Node node = new Node(game.getBoard());
    	
		//*************
    	//Sorting the moves by value
    	//*************
    	
    	ArrayList<int[][]> moves = game.getAllValidMoves(min);
		Object[] bob = moves.toArray();
		/*for(int i=1; i < moves.size(); ++i){
			int j =i;
			int a = game.evalMove(moves.get(i),true);
			while((j>0)&& (game.evalMove(moves.get(j-1), true) > a)){
				bob[j] = moves.get(j-1);
				j--;
			}
			bob[j]=moves.get(i);
		}*/
		
		//*************
    	//Check if the game is in a winning situation
    	//*************
		
        if (game.getAllValidMoves(white).size() == 0 || game.getAllValidMoves(black).size() == 0){ 

            //node.point = board.evalMove(node.move);
            
             return game.checkForWinner();
         } 
         
         
         else if (depth == 0){
        	 System.out.println("test~ 1!");

         	return game.evalBoard(white);
         }
        
        
		//*************
    	//Alpha beta....
		//*************

        else {
            if (min == true) {    		
            	pos ++;
                for (int x = 0; x < game.getAllValidMoves(white).size(); x++) {
                	
                    //Node n = new Node();
                    //n.copy(node);
                    if (game.isValidMove(game.getAllValidMoves(white).get(x))) {
                    	game.doMove(moves.get(x));
                    	//int moveValueBeta = game.evalMove(moves.get(x),true);
                        //node.AddChildren(n);
                        //n.move = game.getAllValidMoves(white).get(x);
                        //System.out.println("In min:"+ min);
                    	
                    	
                    	System.out.println("");
        				System.out.println("(I: " + x + ") (Depth: " + depth + ") (White? " + white + ") (Value:" + alpha +  ") ( NumMoves" + moves.size() + ")");
        				System.out.println("MOVING: " + Utils.intToBoardCoordFormatted(moves.get(x)));
        				System.out.println("------------------------------");
        				game.printBoard();
                        int val = minimaxAB(false, depth - 1, alpha, beta);
                        
                        
        				game.undoMove(moves.get(x));
        				
                        if (val < beta) {
                            beta = val;
                           // n.parent.point = val;
                        }

                        //cutoff branch
                        checkAlphaBeta(alpha, beta);                        
                        if(cutOff)
                        	++x;
                        

                    }
                }
                //System.out.println("Out min:"+ min);
                return beta;
            }

            if (min == false) {
                for (int x = 0; x < game.getAllValidMoves(black).size(); x++) {
                	
                	// Node n = new Node();
                   // n.copy(node);
                    if (game.isValidMove(game.getAllValidMoves(black).get(x)) == true) {
                    	game.doMove(moves.get(x));
                    	//int moveValueAlpha = game.evalMove(moves.get(x), false);
                        //node.AddChildren(n);
                        //n.move = game.getAllValidMoves(black).get(x);
                        //System.out.println("In min:"+ min);
                        int val = minimaxAB( true, depth - 1, alpha, beta);
                        
        				game.undoMove(moves.get(x));

                        if (val > alpha) {
                            alpha = val;
                           // n.parent.point = val;
                        }
                        //cutoff branch
                        checkAlphaBeta(alpha, beta);
                        if(cutOff){
                        	++x;
                        }

                    }

                }
                //System.out.println("Out min:"+ min);
                return alpha;

            }

        }
        return -1000000000;


    }
	
	
    private void checkAlphaBeta(int alpha, int beta){
		try{
			//verifier si on a besoin de check le branche enfant ou juste le cut off
			if (alpha >= beta)
				cutOff = true;
			else
				cutOff = false;
		}catch(Exception e){
			System.out.println("ERROR");
		}
	}
}
